#include "water_machine.h"
#include <stdio.h>
#include "uv_led.h"
#include "valve_control.h"
#include "key.h"
#include "flow_meter.h"
#include "ds18b20.h"
#include "hmi_ringBuf.h"


// 内部函数声明
void hmi_show_run_state(char* str);                 //完成 发送状态到屏
void hmi_show_water_usage(float volume, float balance);//完成 hmi 显示用水量等结果
void hmi_show_userId(uint32_t user_id);             //完成 hmi 显示用户ID

bool start_button_pressed(void);                    //完成 启动按钮
bool stop_button_pressed(void);                     //完成 停止按钮
float calculate_water_volume(uint32_t pulse);       //完成 根据脉冲数计算取水量
float calculate_water_cost(float volume);           //完成 计算金额

uint32_t get_current_time(void);                    //完成 获取当前时间
float Get_Temperature(void);                        //完成 获取环境温度

bool card_swiped(void);                             //TODO: 刷卡
bool qr_code_scanned(void);                         //TODO: 扫码
bool get_user_info_from_server(UserInfo* user);     //TODO: 4G 从服务器获取用户数据

void send_valve_failure_alert(void);                //TODO: 4G 发送阀门关闭错误
void send_water_usage_to_server(uint32_t user_id, float volume, float cost); //TODO: 4G取水结束，发送取水量



// 当前运行模式指针
Mode_Struct *Run_Mode_Now;

// 各种运行模式实例
Mode_Struct Run_Mode_Wait_User_Info;
Mode_Struct Run_Mode_Wait_Start_Button;
Mode_Struct Run_Mode_Water_Dispensing;
Mode_Struct Run_Mode_Wait_Valve_Close;
Mode_Struct Run_Mode_Settlement;

// 取水机模式结构体变量
Run_Water_Struct Run_Water_Data;

// 用户和设备信息
UserInfo current_user;
DeviceInfo device_info = {0};

/*等待用户信息模式初始化*/
void Run_Mode_Wait_User_Info_Init(void) {
    Run_Mode_Wait_User_Info.mode_enter = Run_Mode_Wait_User_Info_Enter;
    Run_Mode_Wait_User_Info.mode_exit = Run_Mode_Wait_User_Info_Exit;
    Run_Mode_Wait_User_Info.mode_run = Run_Mode_Wait_User_Info_Run;
}

/*等待开始按钮模式初始化*/
void Run_Mode_Wait_Start_Button_Init(void) {
    Run_Mode_Wait_Start_Button.mode_enter = Run_Mode_Wait_Start_Button_Enter;
    Run_Mode_Wait_Start_Button.mode_exit = Run_Mode_Wait_Start_Button_Exit;
    Run_Mode_Wait_Start_Button.mode_run = Run_Mode_Wait_Start_Button_Run;
}

/*取水模式初始化*/
void Run_Mode_Water_Dispensing_Init(void) {
    Run_Mode_Water_Dispensing.mode_enter = Run_Mode_Water_Dispensing_Enter;
    Run_Mode_Water_Dispensing.mode_exit = Run_Mode_Water_Dispensing_Exit;
    Run_Mode_Water_Dispensing.mode_run = Run_Mode_Water_Dispensing_Run;
}

/*等待阀门关闭模式初始化*/
void Run_Mode_Wait_Valve_Close_Init(void) {
    Run_Mode_Wait_Valve_Close.mode_enter = Run_Mode_Wait_Valve_Close_Enter;
    Run_Mode_Wait_Valve_Close.mode_exit = Run_Mode_Wait_Valve_Close_Exit;
    Run_Mode_Wait_Valve_Close.mode_run = Run_Mode_Wait_Valve_Close_Run;
}

/*结算模式初始化*/
void Run_Mode_Settlement_Init(void) {
    Run_Mode_Settlement.mode_enter = Run_Mode_Settlement_Enter;
    Run_Mode_Settlement.mode_exit = Run_Mode_Settlement_Exit;
    Run_Mode_Settlement.mode_run = Run_Mode_Settlement_Run;
}

/*所有模式初始化*/
void Run_Mode_Init(void) {
    // 初始化各个模式
    Run_Mode_Wait_User_Info_Init();
    Run_Mode_Wait_Start_Button_Init();
    Run_Mode_Water_Dispensing_Init();
    Run_Mode_Wait_Valve_Close_Init();
    Run_Mode_Settlement_Init();
    
    // 默认启动等待用户信息模式
    Run_Mode_Now = &Run_Mode_Wait_User_Info;
    Run_Mode_Now->mode_enter();
}

/*等待用户信息模式进入*/
void Run_Mode_Wait_User_Info_Enter(void) {
    hmi_show_run_state("等待用户信息进入");
}

/*等待用户信息模式运行*/
void Run_Mode_Wait_User_Info_Run(void) {
    // 检查是否有刷卡或扫码事件
    if (card_swiped() || qr_code_scanned()) {
        // 上传刷卡信息到服务器或接收二维码返回的用户信息
        if (get_user_info_from_server(&current_user)) {
            // 解析数据，获取用户id和账户余额
            // 切换到等待按下开始按钮状态
            Switch_To_Wait_Start_Button_Mode();
        }
    }
}

void Run_Mode_Wait_User_Info_Exit(void) {
    hmi_show_run_state("等待用户信息状态退出");
}

/*等待开始按钮模式进入*/
void Run_Mode_Wait_Start_Button_Enter(void) {
    // 设备状态2等待按键超时时间清零
    device_info.wait_start_time = get_current_time();
    
    hmi_show_run_state("等待开始按钮");
}

/*等待开始按钮模式运行*/
void Run_Mode_Wait_Start_Button_Run(void) {
    // 计算经过的时间
    uint32_t elapsed_time = get_current_time() - device_info.wait_start_time;
    
    // 在未超过设置阈值时间内，用户按下开始按钮
    if (start_button_pressed()) {
        Switch_To_Water_Dispensing_Mode();
    }
    // 超过设置阈值后还未按下开始按钮
    else if (elapsed_time > WAIT_START_BUTTON_TIMEOUT) {
        // 系统取水量清0
        Run_Water_Data.water_volume = 0.0;
        // 进入状态5 结算状态
        Switch_To_Settlement_Mode();
    }
}

/*等待开始按钮模式退出*/
void Run_Mode_Wait_Start_Button_Exit(void) {
    // 暂时为空
}

/*取水模式进入*/
void Run_Mode_Water_Dispensing_Enter(void) {
    // 本次取水量清零
    Run_Water_Data.water_volume = 0.0;
    
    // 打开紫外灯，按照默认强度设置紫外灯输出强度
    UV_LED_Control(1, 80);         // 打开UV LED，亮度80%
    device_info.uv_led_state = 1;
    device_info.uv_led_intensity = UV_LED_HIGH_INTENSITY;
    
    // 打开取水阀
    ValveControl_WaterValve_Open();
    device_info.water_valve_state = 1;
    
    // 判断泄水阀状态，如果是开状态或关闭中状态，则关闭泄水阀
    if (device_info.drain_valve_state == VALVE_STATE_OPEN || 
        device_info.drain_valve_state == VALVE_STATE_CLOSING) {
        ValveControl_DrainValve_Close();
        device_info.drain_valve_state = VALVE_STATE_CLOSE;
    }
    
    hmi_show_run_state("取水中");
}

/*取水模式运行*/
void Run_Mode_Water_Dispensing_Run(void) {
    // 定时读取流量计脉冲数，脉冲数已保存在pulse中，并计算用水金额
    Run_Water_Data.pulse_count = FlowMeter_GetPulseCount();
    Run_Water_Data.water_volume = calculate_water_volume(Run_Water_Data.pulse_count);
    Run_Water_Data.water_cost = calculate_water_cost(Run_Water_Data.water_volume);
    
    // 根据紫外灯温度，调整紫外强度
    device_info.uv_led_temperature = (float)UV_LED_Get_Temperature(0);      //TODO: 修改计算逻辑
    if (device_info.uv_led_temperature > UV_LED_HIGH_TEMPERATURE_THRESHOLD) {
        UV_LED_AdjustBrightness(50);     //设置低亮度
        device_info.uv_led_intensity = UV_LED_LOW_INTENSITY;
    } else if (device_info.uv_led_temperature < UV_LED_LOW_TEMPERATURE_THRESHOLD) {
        UV_LED_AdjustBrightness(80);     //设置高亮度
        device_info.uv_led_intensity = UV_LED_HIGH_INTENSITY;
    }
    
    // 如果用户余额-用水金额<最低余额阈值,则关闭取水阀，关闭紫外灯，切换到状态4
    if ((current_user.balance - Run_Water_Data.water_cost) < MINIMUM_BALANCE_THRESHOLD) {
        ValveControl_WaterValve_Close();
        device_info.water_valve_state = 0;
        UV_LED_Control(0, 0);     //关闭 UV LED
        device_info.uv_led_state = 0;
        Switch_To_Wait_Valve_Close_Mode();
    }
    // 取水期间如果按下停止按钮，则关闭取水阀、关闭紫外灯，切换到状态4
    else if (stop_button_pressed()) {
        ValveControl_WaterValve_Close();
        device_info.water_valve_state = 0;
        UV_LED_Control(0, 0);    //关闭 UV LED
        device_info.uv_led_state = 0;
        Switch_To_Wait_Valve_Close_Mode();
    }
}

/*取水模式退出*/
void Run_Mode_Water_Dispensing_Exit(void) {
    // 暂时为空
}

/*等待阀门关闭模式进入*/
void Run_Mode_Wait_Valve_Close_Enter(void) {
    // 记录阀门开始关闭的时间
    device_info.water_valve_close_time = get_current_time();
    
    hmi_show_run_state("等待阀门关闭");
}

/*等待阀门关闭模式运行*/
void Run_Mode_Wait_Valve_Close_Run(void) {
    // 计算经过的时间
    uint32_t elapsed_time = get_current_time() - device_info.water_valve_close_time;
    
    // 如果经过时间大于设置关闭时间阈值（秒），切换到状态5 结算状态
    if (elapsed_time > VALVE_CLOSE_TIMEOUT) {
        Switch_To_Settlement_Mode();
    }
    // 在超时时间内返回取水阀关闭状态，直接切换到状态5 结算状态
    else if (ValveControl_IsWaterValveClosed()) {
        Switch_To_Settlement_Mode();
    }
}

/*等待阀门关闭模式退出*/
void Run_Mode_Wait_Valve_Close_Exit(void) {
    // 如果是超时切换状态，则发送取水阀关阀故障信息
    uint32_t elapsed_time = get_current_time() - device_info.water_valve_close_time;
    if (elapsed_time > VALVE_CLOSE_TIMEOUT) {
        send_valve_failure_alert();
    }
    
    // 如果环境温度小于设定阈值，打开泄水阀，同时保存打开泄水阀的时间
    device_info.environment_temperature = Get_Temperature();
    if (device_info.environment_temperature < ENVIRONMENT_TEMPERATURE_THRESHOLD) {
        ValveControl_DrainValve_Open();
        device_info.drain_valve_state = VALVE_STATE_OPEN;
        device_info.drain_start_time = get_current_time();
    }
}

/*结算模式进入*/
void Run_Mode_Settlement_Enter(void) {
    // 计算本次用水量，发送用户取水信息到服务器
    Run_Water_Data.water_volume = calculate_water_volume(Run_Water_Data.pulse_count);
    send_water_usage_to_server(current_user.id, Run_Water_Data.water_volume, Run_Water_Data.water_cost);
    
    // 显示本次取水量和剩余金额在屏幕
    hmi_show_water_usage(Run_Water_Data.water_volume, current_user.balance - Run_Water_Data.water_cost);
    
    // 记录结算开始时间
    Run_Water_Data.settlement_time = get_current_time();
    
    hmi_show_run_state("结算中");
}

/*结算模式运行*/
void Run_Mode_Settlement_Run(void) {
    // 如果泄水阀打开，并且当前时间减去打开泄水阀时的时间大于设定时间阈值
    if (device_info.drain_valve_state == VALVE_STATE_OPEN && 
        (get_current_time() - device_info.drain_start_time) > DRAIN_DURATION_THRESHOLD) {
        
        // 开始关闭泄水阀
        ValveControl_DrainValve_Close();
        device_info.drain_valve_state = VALVE_STATE_CLOSING;
        device_info.drain_close_start_time = get_current_time();
    }
    
    // 如果泄水阀处于关闭中状态，且累积关闭时间大于设定时间阈值，修改泄水阀为关闭状态
    if (device_info.drain_valve_state == VALVE_STATE_CLOSING && 
        (get_current_time() - device_info.drain_close_start_time) > DRAIN_CLOSE_DURATION_THRESHOLD) {
        device_info.drain_valve_state = VALVE_STATE_CLOSE;
    }
    
    // 计算显示经过的时间
    uint32_t elapsed_time = get_current_time() - Run_Water_Data.settlement_time;
    
    // 超过设定显示时间，并且泄水阀为关闭状态，转为状态1
    if (elapsed_time > SETTLEMENT_DISPLAY_DURATION &&  
        device_info.drain_valve_state == VALVE_STATE_CLOSE) {
        Switch_To_Wait_User_Info_Mode();
    }
}

/*结算模式退出*/
void Run_Mode_Settlement_Exit(void) {
    // 暂时为空
}

/*运行模式切换逻辑实现*/
void Logic_Run_Mode_Switch(void) {
    // 此函数可根据实际需求实现自动状态切换逻辑
    // 当前实现为空，状态切换通过各状态内部调用Switch函数完成
}

/*状态切换函数实现*/

void Switch_To_Wait_User_Info_Mode(void) {
    if (Run_Mode_Now != &Run_Mode_Wait_User_Info) {
        if (Run_Mode_Now && Run_Mode_Now->mode_exit) {
            Run_Mode_Now->mode_exit();
        }
        Run_Mode_Now = &Run_Mode_Wait_User_Info;
        if (Run_Mode_Now && Run_Mode_Now->mode_enter) {
            Run_Mode_Now->mode_enter();
        }
    }
}

void Switch_To_Wait_Start_Button_Mode(void) {
    if (Run_Mode_Now != &Run_Mode_Wait_Start_Button) {
        if (Run_Mode_Now && Run_Mode_Now->mode_exit) {
            Run_Mode_Now->mode_exit();
        }
        Run_Mode_Now = &Run_Mode_Wait_Start_Button;
        if (Run_Mode_Now && Run_Mode_Now->mode_enter) {
            Run_Mode_Now->mode_enter();
        }
    }
}

void Switch_To_Water_Dispensing_Mode(void) {
    if (Run_Mode_Now != &Run_Mode_Water_Dispensing) {
        if (Run_Mode_Now && Run_Mode_Now->mode_exit) {
            Run_Mode_Now->mode_exit();
        }
        Run_Mode_Now = &Run_Mode_Water_Dispensing;
        if (Run_Mode_Now && Run_Mode_Now->mode_enter) {
            Run_Mode_Now->mode_enter();
        }
    }
}

void Switch_To_Wait_Valve_Close_Mode(void) {
    if (Run_Mode_Now != &Run_Mode_Wait_Valve_Close) {
        if (Run_Mode_Now && Run_Mode_Now->mode_exit) {
            Run_Mode_Now->mode_exit();
        }
        Run_Mode_Now = &Run_Mode_Wait_Valve_Close;
        if (Run_Mode_Now && Run_Mode_Now->mode_enter) {
            Run_Mode_Now->mode_enter();
        }
    }
}

void Switch_To_Settlement_Mode(void) {
    if (Run_Mode_Now != &Run_Mode_Settlement) {
        if (Run_Mode_Now && Run_Mode_Now->mode_exit) {
            Run_Mode_Now->mode_exit();
        }
        Run_Mode_Now = &Run_Mode_Settlement;
        if (Run_Mode_Now && Run_Mode_Now->mode_enter) {
            Run_Mode_Now->mode_enter();
        }
    }
}

/**
 * @brief 取水机主任务函数
 * @param argument 任务参数（未使用）
 */
void WaterMachineTask(void *argument)
{
    // 状态机初始化
    Run_Mode_Init();
    
    // 主循环
    for(;;)
    {
        // 调用运行模式切换逻辑（处理自动状态切换）
        Logic_Run_Mode_Switch(); //TODO: 根据需要增加代码
        
        // 执行当前模式的运行函数
        if (Run_Mode_Now != NULL && Run_Mode_Now->mode_run != NULL) {
            Run_Mode_Now->mode_run();
        }
        osDelay(100);
    }
}

/**
 * @brief 检测是否刷卡
 * @return true-已刷卡, false-未刷卡
 */
bool card_swiped(void) {
    // TODO: 实现刷卡检测功能
    return false;
}

/**
 * @brief 检测是否扫码
 * @return true-已扫码, false-未扫码
 */
bool qr_code_scanned(void) {
    // TODO: 实现扫码检测功能
    return false;
}

/**
 * @brief 从服务器获取用户数据
 * @param user 用户信息结构体指针
 * @return true-获取成功, false-获取失败
 */
bool get_user_info_from_server(UserInfo* user) {
    // TODO: 实现从服务器获取用户数据功能
    (void)user;
    return false;
}

/**
 * @brief 检测启动按钮是否按下
 * @return true-已按下, false-未按下
 */
bool start_button_pressed(void) {
    int8_t key_value;
    osStatus_t status;
    
    // 尝试从按键消息队列中获取按键值（非阻塞）
    status = osMessageQueueGet(key_queue_Handle, &key_value, NULL, 0);
    
    if (status == osOK) {
        // 判断是否为启动按钮（开门按键）
        if (key_value == KEY_OPEN) {
            return true;
        }
    }
    return false;
}

/**
 * @brief 检测停止按钮是否按下
 * @return true-已按下, false-未按下
 */
bool stop_button_pressed(void) {
    int8_t key_value;
    osStatus_t status;
    
    // 尝试从按键消息队列中获取按键值（非阻塞）
    status = osMessageQueueGet(key_queue_Handle, &key_value, NULL, 0);
    
    if (status == osOK) {
        // 判断是否为启动按钮（开门按键）
        if (key_value == KEY_CLOSE) {
            return true;
        }
    }
    return false;
}

/**
 * @brief 根据脉冲数计算取水量
 * @param pulse 脉冲数
 * @return 计算出的水量(升)
 */
float calculate_water_volume(uint32_t pulse) {
    // 根据当量计算水量: 水量(升) = 脉冲数 × 每脉冲对应的升数
    return (float)pulse * FLOW_METER_LITERS_PER_PULSE;
}

/**
 * @brief 计算用水金额
 * @param volume 用水量（升）
 * @return 计算出的金额（元）
 */
float calculate_water_cost(float volume) {
    // 金额计算: 金额 = 水量 × 单价
    return volume * WATER_PRICE_PER_LITER;
}

/**
 * @brief 发送阀门故障警报
 */
void send_valve_failure_alert(void) {
    // TODO: 实现阀门故障警报发送功能
}

/**
 * @brief 发送用水量数据到服务器
 * @param user_id 用户ID
 * @param volume 用水量
 * @param cost 金额
 */
void send_water_usage_to_server(uint32_t user_id, float volume, float cost) {
    // TODO: 实现用水量数据发送功能
    (void)user_id;
    (void)volume;
    (void)cost;
}

/**
 * @brief 获取当前系统时间
 * @return 当前系统时间戳（毫秒）
 */
uint32_t get_current_time(void) {
    // 使用CMSIS-OS v2接口获取系统时间（毫秒）
    return (uint32_t)osKernelGetTickCount();
}

/**
 * @brief 获取环境温度
 * @return 当前环境温度
 */
float Get_Temperature(void) {
    float temperature;
    // 获取互斥锁
    if (osMutexAcquire(ds18b20MutexHandle, 1000) == osOK) {
        // 获取温度值
        temperature = DS18B20_GetTemperature();
        
        // 释放互斥锁
        osMutexRelease(ds18b20MutexHandle);
    }
    return temperature;
}

/**
 * @brief 在HMI上显示运行状态信息
 * @param str 要显示的字符串内容
 * @details 该函数将字符串内容按照HMI协议格式封装后发送到HMI显示屏
 *          协议格式为: "t0.txt=" + 内容 + "\xFF\xFF\xFF"
 *          其中t0.txt是HMI上的文本控件名
 */
void hmi_show_run_state(char* str)
{
    if (str != NULL) {
        static char hmi_buffer[50];
        uint8_t cmd_len;
        
        // 构造HMI命令
        cmd_len = snprintf(hmi_buffer, sizeof(hmi_buffer), "t0.txt=\"%s\"", str);
        
        // 添加HMI结束符(根据实际HMI协议调整)
        hmi_buffer[cmd_len] = 0xFF;
        hmi_buffer[cmd_len + 1] = 0xFF;
        hmi_buffer[cmd_len + 2] = 0xFF;
        
        // 发送到HMI
        send_str_hmi((uint8_t*)hmi_buffer, cmd_len + 3);
    }
}

/**
 * @brief 在HMI上显示用水量和余额信息
 * @param volume 用水量（升）
 * @param balance 余额（元）
 * @details 该函数将用水量和余额分别显示在HMI的不同文本控件上
 *          用水量显示在t1.txt控件，余额显示在t2.txt控件
 */
void hmi_show_water_usage(float volume, float balance) {
    static char hmi_buffer[64];
    uint8_t cmd_len;
    
    // 显示用水量到t1.txt控件
    cmd_len = snprintf(hmi_buffer, sizeof(hmi_buffer), "t1.txt=\"用水量:%.2fL\"", volume);
    hmi_buffer[cmd_len] = 0xFF;
    hmi_buffer[cmd_len + 1] = 0xFF;
    hmi_buffer[cmd_len + 2] = 0xFF;
    send_str_hmi((uint8_t*)hmi_buffer, cmd_len + 3);
    
    // 显示余额到t2.txt控件
    cmd_len = snprintf(hmi_buffer, sizeof(hmi_buffer), "t2.txt=\"余额:%.2f元\"", balance);
    hmi_buffer[cmd_len] = 0xFF;
    hmi_buffer[cmd_len + 1] = 0xFF;
    hmi_buffer[cmd_len + 2] = 0xFF;
    send_str_hmi((uint8_t*)hmi_buffer, cmd_len + 3);
}

/**
 * @brief 在HMI上显示用户ID信息
 * @param user_id 用户ID（32位无符号整数）
 * @details 该函数将用户ID格式化为10位字符串并显示在HMI的t3.txt控件上
 *          不足10位的前面补0，例如: 0000123456
 */
void hmi_show_userId(uint32_t user_id) {
    static char hmi_buffer[50];
    uint8_t cmd_len;
    
    // 格式化用户ID为10位字符串，不足位数前面补0
    cmd_len = snprintf(hmi_buffer, sizeof(hmi_buffer), "t3.txt=\"用户ID:%010u\"", user_id);
    hmi_buffer[cmd_len] = 0xFF;
    hmi_buffer[cmd_len + 1] = 0xFF;
    hmi_buffer[cmd_len + 2] = 0xFF;
    send_str_hmi((uint8_t*)hmi_buffer, cmd_len + 3);
}

/*
// 在代码中使用
void example_usage(void) {
    uint32_t pulses = FlowMeter_GetPulseCount();
    float volume = calculate_water_volume(pulses);  // 计算水量
    float cost = calculate_water_cost(volume);      // 计算金额
    
    printf("脉冲数: %lu, 水量: %.2f 升, 金额: %.2f 元\n", pulses, volume, cost);
}

*/
